package JavaEE_notes.common_API.Thread;

import JavaEE_notes.common_API.Thread.pojo.MyCallable;
import JavaEE_notes.common_API.Thread.pojo.MyRunnable;
import JavaEE_notes.common_API.Thread.pojo.MyThread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 练习线程 几种创建线程的方式
 * @author TaiZai
 * @data 2024/9/24 11:32
 */
public class api_Thread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1、直接创建子类继承 Thread
        Thread t1 = new MyThread();
        t1.start(); // 启动线程
        // t1.run();;

        for (int i = 0; i < 5; i++) {
            System.out.println("主线程输出--" + i);
        }
        /*
        * MyThread 和 主线程会产生争夺CUP的情况，无法控制先执行哪个线程
        * 因此每次的输出结果都是不同的
        * 如果是直接调用run()方法，会先执行MyThread再执行main
        * */

        // 2、通过实现 Runnable 接口创建线程
//        Runnable r = new MyRunnable();
//        new Thread(r).start(); // 将任务对象交给线程对象处理
//
//        for (int i = 0; i < 5; i++) {
//            System.out.println("主线程输出--" + i);
//        }

        /*
        * 同样抢占CPU的情况，因此每次的输出结果都是不同的
        * */

        // 对第二种方式可以采用匿名内部类的方式创建
        // 直接创建 Runnable 接口的匿名内部类形式
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                for (int i = 0; i < 5; i++) {
//                    System.out.println("匿名内部类线程--" + i);
//                }
//            }
//        }).start();
//
//        // 更加简化
//        new Thread(() -> {
//            for (int i = 0; i < 5; i++) {
//                System.out.println("Lambda 线程--" + i);
//            }
//        }).start();

        // 3、Callable 接口创建线程
        // 创建一个Callable 对象
//        Callable<String> call = new MyCallable(100);
//        // 将Callable 封装成一个 FutureTask 对象
//        FutureTask<String> f1 = new FutureTask<>(call);
//        new Thread(f1).start(); // 将任务对象交给线程处理并启动线程
//
//        // 获取线程执行完毕的结果，如果上面的线程没有执行完毕，此处的代码会陷入等待状态
//        String res1 = f1.get();
//        System.out.println(res1);
        /*
        * 与 Runnable 线程的区别：
        * 1、Callable 接口可以有返回值，FutureTask 也能有返回值
        * 2、FutureTask 类是 Future 接口的一个实现类，可以对线程执行的结果进行取消、查询是否完成等操作
        * 3、Callable 接口中的 call() 方法可以抛出 checked 异常，FutureTask 类中的 get() 方法可以捕获并抛出 checked
         */
    }
}
